package cz.muni.fi.pb138.xml.wrda.controller;

import cz.muni.fi.pb138.xml.wrda.servise.XSDService;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;


/**
 *
 * @author Ondřej Chrastina 430596@mail.muni.cz
 */
@Controller
@RequestMapping("/xsd")
public class XSDController {

    @Autowired
    private XSDService xsdService;

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView addNew() {
        return new ModelAndView("xsd_add");
    }

    @RequestMapping(value = "/add/", method = RequestMethod.POST)
    public ModelAndView addNew(HttpServletRequest request, @RequestParam CommonsMultipartFile[] fileUpload) {   //dlzka suboru musi byt viac ako 0
        if (fileUpload != null && fileUpload.length > 0) {   // iteracia cez vsetky vybrane subory
            for (CommonsMultipartFile fileToSave : fileUpload) {   // neposlal som blbost ?
                if (!fileToSave.getOriginalFilename().equals("")) {   // typ suboru je .xsd inak to zahadzujeme 
                    if (StringUtils.endsWith(fileToSave.getOriginalFilename(), ".xsd")) {
                        try {
                            xsdService.saveFile(fileToSave.getInputStream(), fileToSave.getOriginalFilename());
                        } catch (IOException ex) {
                            Logger.getLogger(XSDController.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    }
                }
            }
        }

        return new ModelAndView("redirect:/xsd/browse");
    }

    @RequestMapping(value = "/browse", method = RequestMethod.GET)
    public ModelAndView browse() {
        System.out.println(xsdService.printAll());
        return new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNames());
    }

    @RequestMapping(value = "/browse", method = RequestMethod.POST)
    public ModelAndView browseByFileName(HttpServletRequest request) {
        String searchTypeSelect = request.getParameter("searchType");
        String typeNameInput = request.getParameter("typeName");
        String fileNameInput = request.getParameter("fileName");

        //nic neni vybrane
        if (typeNameInput == "" && fileNameInput == "") {
            ModelAndView mw = new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNames());
            mw.addObject("searchTypeSelect", searchTypeSelect);
            mw.addObject("typeNameInput", typeNameInput);
            mw.addObject("fileNameInput", fileNameInput);
            return mw;
        }

        //neni vybran typ
        if (typeNameInput == "") {
            ModelAndView mw = new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNamesByFileName(fileNameInput));
            mw.addObject("searchTypeSelect", searchTypeSelect);
            mw.addObject("typeNameInput", typeNameInput);
            mw.addObject("fileNameInput", fileNameInput);
            return mw;
        }

        //neni vybrano jmeno souboru
        if (fileNameInput == "") {
            if (searchTypeSelect.equals("simple")) {
                ModelAndView mw = new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNamesBySimpleTypeContains(typeNameInput));
                mw.addObject("searchTypeSelect", searchTypeSelect);
                mw.addObject("typeNameInput", typeNameInput);
                mw.addObject("fileNameInput", fileNameInput);
                return mw;
            } else { //Complex types
                ModelAndView mw = new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNamesByComplexTypeContains(typeNameInput));
                mw.addObject("searchTypeSelect", searchTypeSelect);
                mw.addObject("typeNameInput", typeNameInput);
                mw.addObject("fileNameInput", fileNameInput);
                return mw;
            }
        }

        //je zadano oboje
        ModelAndView mw = new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNamesByFileNameAndType(fileNameInput, typeNameInput, searchTypeSelect));
        mw.addObject("searchTypeSelect", searchTypeSelect);
        mw.addObject("typeNameInput", typeNameInput);
        mw.addObject("fileNameInput", fileNameInput);
        return mw;
    }

    @RequestMapping(value = "/browse/{fileName}", method = RequestMethod.GET)
    public ModelAndView browseVersions(@PathVariable String fileName) {
        return new ModelAndView("xsd_versions", "artifacts", xsdService.getAllEntriesByFileName(fileName + ".xsd"));
    }

    @RequestMapping(value = "/browse/{fileName}", method = RequestMethod.POST)
    public ModelAndView browseVersionsFilter(@PathVariable String fileName, HttpServletRequest request) {
        String searchTypeSelect = request.getParameter("searchType");
        String typeNameInput = request.getParameter("typeName");
        if (typeNameInput == "") {
            ModelAndView mw = new ModelAndView("xsd_versions", "artifacts", xsdService.getAllEntriesByFileName(fileName + ".xsd"));
            mw.addObject("searchTypeSelect", searchTypeSelect);
            mw.addObject("typeNameInput", typeNameInput);
            return mw;
        } else {
            if (searchTypeSelect.equals("simple")) {
                ModelAndView mw = new ModelAndView("xsd_versions", "artifacts", xsdService.getAllEntriesByFileNameAndSimpleTypeContains(fileName + ".xsd", typeNameInput));
                mw.addObject("searchTypeSelect", searchTypeSelect);
                mw.addObject("typeNameInput", typeNameInput);
                return mw;
            } else {
                ModelAndView mw = new ModelAndView("xsd_versions", "artifacts", xsdService.getAllEntriesByFileNameAndComplexTypeContains(fileName + ".xsd", typeNameInput));
                mw.addObject("searchTypeSelect", searchTypeSelect);
                mw.addObject("typeNameInput", typeNameInput);
                return mw;
            }
        }

    }

    @RequestMapping(value = "/browse/{fileName}/{timeStamp}")
    public ModelAndView browseXsdEntry(@PathVariable String fileName, @PathVariable String timeStamp) {
        return new ModelAndView("xsd_entry", "xsdEntry", xsdService.getEntryByFileNameAndTimeStamp(fileName, timeStamp));
    }

    @RequestMapping(value = "/delete/{fileName}")
    public ModelAndView deleteAllVersionsXsdEntry(@PathVariable String fileName) {
        xsdService.deleteAllVersionsXsdEntryByName(fileName + ".xsd");
        return new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNames());
    }

    @RequestMapping(value = "/delete/{fileName}/{timeStamp}")
    public ModelAndView deleteXsdEntryTimeStamp(@PathVariable String fileName, @PathVariable String timeStamp) {
        xsdService.deleteXsdEntryTimeStamp(timeStamp);
        return new ModelAndView("xsd_browse", "artifacts", xsdService.getAllEntriesDistinctNames());
    }

    @RequestMapping(value = "/download/{fileName}/{timeStamp}")
    public void donwloadXsdEntryByTimeStamp(@PathVariable String fileName, @PathVariable String timeStamp, HttpServletResponse response) {
        try {
            InputStream inputStream = new ReaderInputStream(xsdService.getXSDContentAsInputStream(timeStamp));
            response.setContentType("application/xml"); //
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
        } catch (IOException ex) {
            Logger.getLogger(XSDController.class.getName()).log(Level.SEVERE, "Can't start downloading file.", ex);
        }
    }
}
